(load "16.ready-set-bang.ss")

(define (deep m)
  (if (zero? m)
      'pizza
      (cons (deep (sub1 m))
            '())))

;; Page 127
(define deepM
  (let ((Rs (quote ()))
        (Ns (quote ())))
    (letrec
      ((D (lambda (m)
            (if (zero? m)
                (quote pizza)
                (cons (D (sub1 m))
                      (quote ()))))))
      (lambda (n)
        (let ((exists (find n Ns Rs)))
         (if (atom? exists)
             (let ((result (D n)))
              (set! Rs (cons result Rs))
              (set! Ns (cons n Ns))
              result)
             exists))))))
;; Page 128
(define deepM
  (let ((Rs (quote ()))
        (Ns (quote ()))
        (D (lambda (m)
             (if (zero? m)
                 (quote pizza)
                 (cons (deepM (sub1 m))
                       (quote ()))))))
    (lambda (n)
      (let ((exists (find n Ns Rs)))
       (if (atom? exists)
           (let ((result (D n)))
            (set! Rs (cons result Rs))
            (set! Ns (cons n Ns))
            result)
           exists)))))

;; Page 130
(define deepM
  (let ((Rs (quote ()))
        (Ns (quote ())))
    (lambda (n)
      (let ((exists (find n Ns Rs)))
       (if (atom? exists)
           (let ((result
                   (if (zero? n)
                       (quote pizza)
                       (cons (deepM (sub1 n))
                             (quote ())))))
             (set! Rs (cons result Rs))
             (set! Ns (cons n Ns))
             result)
           exists)))))

;; Page 131
(define consC
  (let ((N 0))
   (lambda (x y)
     (set! N (add1 N))
     (cons x y))))

;; Page 132
(define (deep m)
  (if (zero? m)
      'pizza
      (consC (deep (sub1 m))
             '())))
(define counter)
(define set-counter)

(define consC
  (let ((N 0))
   (set! counter (lambda () N))
   (set! set-counter (lambda (x) (set! N x)))
   (lambda (x y)
     (set! N (add1 N))
     (cons x y))))

;; Page 134
(define (supercounter f)
  (letrec ((S (lambda (n)
                (if (zero? n)
                    (f n)
                    (begin (f n)
                           (S (sub1 n)))))))
    (S 1000)
    (counter)))

;; Pgae 139
(define (rember1*C a l)
  (letrec ((R (lambda (l oh)
                (cond
                  ((null? l)
                   (oh 'no))
                  ((atom? (car l))
                   (if (eq? (car l) a)
                       (cdr l)
                       (consC (car l) (R (cdr l) oh))))
                  (else
                    (let ((new-car
                            (letcc oh (R (car l) oh))))
                      (if (atom? new-car)
                          (consC (car l) (R (cdr l) oh))
                          (consC new-car (cdr l)))))))))
    (let ((new-l (letcc oh (R l oh))))
     (if (atom? new-l)
         l
         new-l))))

;; Pgae 139
(define (rember1*C2 a l)
  (letrec ((R (lambda (l)
                (cond
                  ((null? l) '())
                  ((atom? (car l))
                   (if (eq? (car l) a)
                       (cdr l)
                       (consC (car l)
                              (R (cdr l)))))
                  (else
                    (let ((av (R (car l))))
                     (if (eqlist? av (car l))
                         (consC (car l) (R (cdr l)))
                         (consC av (cdr l)))))))))
    (R l)))
